/**
 * 表单验证
 * @author 木人心
 * @version 1.0.0
 */
import { Required } from '@utils/form-rule/type'
import { ObjectUtil } from '@utils/object-util'

// region TODO 必填项
export const required = function (message = '此项为必填项', trigger = 'blur') {
  return { required: true, message, trigger }
} as Required;

// 添加语法糖
['blur', 'change'].forEach(trigger => {
  required[trigger] = (message: string) => required(message, trigger)
})

// endregion

// region TODO 手动验证 - 类型 ElValidator
export interface ElValidator {
  validator(rule: any, value: any, callback: (error?: Error) => void): void,

  trigger: string
  [p: string]: any
}

// endregion

// region TODO 手机号
export function phoneTag (value: string) {
  // 中国电信号码格式验证 手机段：
  // 133,149,153,173,177,180,181,189,191,193,199,1349,1410,1700,1701,1702
  const phoneTagDx = /(?:^(?:\+86)?1(?:33|49|53|7[37]|8[019]|9[139])\d{8}$)|(?:^(?:\+86)?1349\d{7}$)|(?:^(?:\+86)?1410\d{7}$)|(?:^(?:\+86)?170[0-2]\d{7}$)/

  // 中国联通号码格式验证 手机段：
  // 130,131,132,145,146,155,156,166,171,175,176,185,186,1704,1707,1708,1709
  const phoneTagLt = /(?:^(?:\+86)?1(?:3[0-2]|4[56]|5[56]|66|7[156]|8[56])\d{8}$)|(?:^(?:\+86)?170[47-9]\d{7}$)/

  // 中国移动号码格式验证 手机段：
  // 134,135,136,137,138,139,147,148,150,151,152,157,158,159,178,182,183,184,187,188,198,1440,1703,1705,1706
  const phoneTagYd = /(?:^(?:\+86)?1(?:3[4-9]|4[78]|5[0-27-9]|78|8[2-478]|98)\d{8}$)|(?:^(?:\+86)?1440\d{7}$)|(?:^(?:\+86)?170[356]\d{7}$)/
  if (phoneTagDx.test(value) || phoneTagLt.test(value) || phoneTagYd.test(value)) {
    return undefined
  } else {
    return new Error('手机号格式不正确')
  }
}

export const phoneRule: ElValidator = {
  validator (rule, value, callback) {
    callback(ObjectUtil.isNotEmpty(value) ? phoneTag(value) : undefined)
  },
  trigger: 'blur'
}
// endregion

// region TODO 账号
export function usernameTag (value: string) {
  const username = /^[\w]{8,16}$/
  if (username.test(value)) {
    return undefined
  } else {
    return new Error('账号为8 ~ 16位字母、数字')
  }
}

export const usernameRule: ElValidator = {
  validator (rule, value, callback) {
    callback(ObjectUtil.isNotEmpty(value) ? usernameTag(value) : undefined)
  },
  trigger: 'blur'
}

// endregion

// region TODO 密码
export function passwordTag (value) {
  if (ObjectUtil.isEmpty(value)) return undefined
  const password = /^(?=.*[A-Za-z])(?=.*\d)[\w\-+.@#$%^&*!]{8,16}$/
  const passwordTwo = /^[\w\-+.]{8,16}$/
  if (password.test(value)) {
    return undefined
  } else if (passwordTwo.test(value)) {
    return new Error('密码至少包含1位字母或数字')
  } else {
    return new Error('密码为8 ~ 16位字母、数字')
  }
}

export const passwordRule: ElValidator = {
  validator (rule, value, callback) {
    callback(ObjectUtil.isNotEmpty(value) ? passwordTag(value) : undefined)
  },
  trigger: 'blur'
}
// endregion

// region TODO 地理坐标 position
export function positionTag (value: string) {
  const position = /^((-?180)|(-?1[0-7]\d)|(-?[1-9]\d)|(-?[1-9])|0)(\.\d+)?,((-?90)|(-?[1-8]\d)|(-?[1-9])|0)(\.\d+)?$/
  if (position.test(value)) {
    return undefined
  } else {
    return Error('坐标格式为(±180,±90)')
  }
}

export const positionRule: ElValidator = {
  validator (rule, value, callback) {
    callback(ObjectUtil.isNotEmpty(value) ? positionTag(value) : undefined)
  },
  trigger: 'blur'
}
// endregion

// region TODO Ip ip
export function ipTag (value) {
  const tag = /^(1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9]?[0-9])(\.(1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9]?[0-9])){3}$/
  if (tag.test(value)) {
    return undefined
  } else {
    return Error('坐标格式为(±180,±90)')
  }
}

export const ipRule: ElValidator = {
  validator (rule, value, callback) {
    callback(positionTag(value))
  },
  trigger: 'blur'
}
// endregion

// region TODO 数字 number
export function numberTag (value) {
  if (ObjectUtil.isEmpty(value) || !isNaN(Number(value))) {
    return undefined
  } else {
    return Error('此项应为正整数')
  }
}

export const numberRule: ElValidator = {
  validator (rule, value, callback) {
    callback(numberTag(value))
  },
  trigger: 'blur'
}
// endregion

// region TODO 正数 positiveNumber
export function positiveNumberTag (value) {
  const isNumber = !isNaN(Number(value))
  if (ObjectUtil.isEmpty(value) || (isNumber && Number(value) > 0)) {
    return undefined
  } else {
    return Error('此项应为正数数字')
  }
}

export const positiveNumberRule: ElValidator = {
  validator (rule, value, callback) {
    callback(numberTag(value))
  },
  trigger: 'blur'
}
// endregion

// region TODO 整数 integer
export function integerTag (value) {
  const tag = /^-?\d+$/
  if (ObjectUtil.isEmpty(value) || tag.test(value)) {
    return undefined
  } else {
    return Error('此项应为正整数')
  }
}

export const integerRule: ElValidator = {
  validator (rule, value, callback) {
    callback(integerTag(value))
  },
  trigger: 'blur'
}
// endregion

// region TODO 正整数 positiveInteger
export function positiveIntegerTag (value) {
  const tag = /^\d+$/
  if (ObjectUtil.isEmpty(value) || tag.test(value)) {
    return undefined
  } else {
    return Error('此项应为正整数')
  }
}

export const positiveIntegerRule: ElValidator = {
  validator (rule, value, callback) {
    callback(positiveIntegerTag(value))
  },
  trigger: 'blur'
}
// endregion
